package data;

import java.util.ArrayList;

/**
 * XMLNode class used to store the nodes and their properties read from the XML file
 * @author  Florian Bacher & Matthias Vavti
 * @version  1.0
 */
public class XMLNode {
	
	private String name;
	/**
	 * @uml.property  name="parent"
	 * @uml.associationEnd  
	 */
	private XMLNode parent;
	private ArrayList<XMLNode> children;
	private boolean canHaveChildren = true;
	private boolean isAttributeName = false;
	private boolean isAttributeValue = false;
	private boolean hasAttributes = false;
	private boolean isValue = false;
	private byte[] salt;
	private byte[] hashValue;
	private boolean isRedacted;
	private boolean publishSalt;
	private int depth = 0;

	public XMLNode(){
		children = new ArrayList<XMLNode>();
	}
	
	/**
	 * Constructor used to create nodes
	 * @param name name of the node
	 * @param parent parent of the node
	 */
	public XMLNode(String name, XMLNode parent){
		this.name = name;
		this.parent = parent;
		children = new ArrayList<XMLNode>();
		this.depth = parent.getDepth()+1;
		parent.addChild(this);
	}
	
	/** 
	 * Constructor needed to create the root nodes 
	 * @param name name of the node
	 */
	public XMLNode(String name){
		this.name = name;
		children = new ArrayList<XMLNode>();
	}
	
	/**
	 * Getter for the Name of the Node
	 * @return  the Name of the Node
	 * @uml.property  name="name"
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * Setter for the Name of the Node
	 * @param name  the Name of the Node
	 * @uml.property  name="name"
	 */
	public void setName(String name) {
		this.name = name;
	}
	
	/**
	 * Getter for the Parent of a Node
	 * @return  the Parent of the Node
	 * @uml.property  name="parent"
	 */
	public XMLNode getParent() {
		return parent;
	}
	
	/**
	 * Setter for the Parent of a Node
	 * @param parent  the Parent of the Node
	 * @uml.property  name="parent"
	 */
	public void setParent(XMLNode parent) {
		if(parent != null)
			this.parent = parent;
	}
	
	/**
	 * Getter for the Childs of a Node
	 * @return  ArrayList with all Childs of the Node
	 * @uml.property  name="children"
	 */
	public ArrayList<XMLNode> getChildren() {
		return children;
	}
	
	/**
	 * Used to add Children to a node
	 * @param child the Children which will be added
	 */
	public void addChild(XMLNode child) {
		if(child != null){
			children.add(child);
			child.setParent(this);
			child.setDepth(this.depth + 1);
		}		
	}
	
	/**
	 * Verifies if the Node can have Children
	 * @return true or false
	 */
	public boolean canHaveChildren() {
		return canHaveChildren;
	}
	
	/**
	 * Sets if the Node can have Children
	 * @param canHaveChildren  true or false
	 * @uml.property  name="canHaveChildren"
	 */
	public void setCanHaveChildren(boolean canHaveChildren) {
		this.canHaveChildren = canHaveChildren;
	}

	/**
	 * Verifies if the Node is an Attribute Name e.G.: <xyz AttributeName="xyz"></xyz>
	 * @param isAttribute true or false
	 */
	public void setIsAttributeName(boolean isAttribute) {
		this.isAttributeName = isAttribute;
	}

	/**
	 * Sets if the Node is an Attribute Name 
	 * @return  true or false
	 * @uml.property  name="isAttributeName"
	 */
	public boolean isAttributeName() {
		return isAttributeName;
	}

	/**
	 * Sets if the Node is a Value e.G.: <xyz>Value</xyz>
	 */
	public void setIsValue(boolean isValue) {
		this.isValue = isValue;
	}

	/**
	 * Verifies if the Node is a Value
	 * @return  true or false
	 * @uml.property  name="isValue"
	 */
	public boolean isValue() {
		return isValue;
	}

	/**
	 * Sets if the Node is an Attribute Value e.G.: <xyz xyz="AttributeValue"></xyz>
	 * @param isAttributeValue true or false
	 */
	public void setIsAttributeValue(boolean isAttributeValue) {
		this.isAttributeValue = isAttributeValue;
	}

	/**
	 * Verifies if the Node is an Attribute Value
	 * @return  true or false
	 * @uml.property  name="isAttributeValue"
	 */
	public boolean isAttributeValue() {
		return isAttributeValue;
	}

	/**
	 * Sets if the Node has Attributes
	 * @param hasAttributes  true or false
	 * @uml.property  name="hasAttributes"
	 */
	public void setHasAttributes(boolean hasAttributes) {
		this.hasAttributes = hasAttributes;
	}

	/**
	 * Verifies if the Node has Attributes
	 * @return true or false
	 */
	public boolean hasAttributes() {
		return hasAttributes;
	}

	/**
	 * Sets the Hash Value of the Node
	 * @param  hashValue
	 * @uml.property  name="hashValue"
	 */
	public void setHashValue(byte[] hashValue) {
		this.hashValue = hashValue;
	}

	/**
	 * Getter for the Hash Value of the Node
	 * @return  byte[] representing the Hashvalue
	 * @uml.property  name="hashValue"
	 */
	public byte[] getHashValue() {
		return hashValue;
	}

	/**
	 * Sets the Salt (Randomizer) of the Node
	 * @param  salt
	 * @uml.property  name="salt"
	 */
	public void setSalt(byte[] salt) {
		this.salt = salt;
	}

	/**
	 * Getter for the Salt of the Node
	 * @return  byte[] representing the Salt
	 * @uml.property  name="salt"
	 */
	public byte[] getSalt() {
		return salt;
	}

	/**
	 * @param publishSalt
	 * @uml.property  name="publishSalt"
	 */
	public void setPublishSalt(boolean publishSalt) {
		this.publishSalt = publishSalt;
	}

	/**
	 * @return
	 * @uml.property  name="publishSalt"
	 */
	public boolean getPublishSalt() {
		return publishSalt;
	}

	/**
	 * @param isRedacted
	 * @uml.property  name="isRedacted"
	 */
	public void setRedacted(boolean isRedacted) {
		this.isRedacted = isRedacted;
	}

	/**
	 * @return
	 * @uml.property  name="isRedacted"
	 */
	public boolean isRedacted() {
		return isRedacted;
	}
	
	public ArrayList<XMLNode> getSiblings(){
		ArrayList<XMLNode> siblings = new ArrayList<XMLNode>();
		for(XMLNode child : parent.getChildren()){
			siblings.add(child);
		}
		siblings.remove(this);
		return siblings;
	}

	/**
	 * @param depth
	 * @uml.property  name="depth"
	 */
	public void setDepth(int depth) {
		this.depth = depth;
	}

	/**
	 * @return
	 * @uml.property  name="depth"
	 */
	public int getDepth() {
		return depth;
	}

}
